//*****************************************************************************
//
//*****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "lm4f120h5qr.h"
#include "board_config.h"
#include "team.h"

#include "SPI.h"

/******************************************************************************
 * Defines
 *****************************************************************************/
#define PORTA                 0x40004000
#define PORTB                 0x40005000
#define PORTC                 0x40006000
#define PORTD                 0x40007000
#define PORTE                 0x40024000
#define PORTF                 0x40025000

#define DISABLE_SYSTICK_IRQ   false
#define ENABLE_SYSTICK_IRQ    true

#define POT_LEFT  1
#define POT_RIGHT 0

extern void PLL_Init(void);
extern void initPortC(void);
/******************************************************************************
 * Global Variables
 *****************************************************************************/
GPIO_PORT *GpioPortA = (GPIO_PORT *) PORTA;
GPIO_PORT *GpioPortB = (GPIO_PORT *) PORTB;
GPIO_PORT *GpioPortC = (GPIO_PORT *) PORTC;
GPIO_PORT *GpioPortD = (GPIO_PORT *) PORTD;
GPIO_PORT *GpioPortE = (GPIO_PORT *) PORTE;
GPIO_PORT *GpioPortF = (GPIO_PORT *) PORTF;

 // Systick Variables
volatile bool mSecondAlert = false;

volatile uint16_t SW2count = 0x00;
volatile uint16_t SW3count = 0x00;
volatile uint16_t SW4count = 0x00;
volatile uint16_t SW5count = 0x00;
volatile uint16_t SW6count = 0x00;

volatile bool SW2button = false;
volatile bool SW3button = false;
volatile bool SW4button = false;
volatile bool SW5button = false;
volatile bool SW6button = false;

 // ADC Variables
volatile uint32_t POT300Value = 0x0000;
volatile uint32_t POT301Value = 0x0000;

 // Timer Variables
volatile uint16_t DisplayPWM = 0x00;

//*****************************************************************************
// External Functions
//*****************************************************************************
extern void PLL_Init(void);
extern void EnableInterrupts(void);
extern void DisableInterrupts(void);
extern void initPortC(void);

extern void initializeSysTick(uint32_t count);
extern void initializeTimer0A(uint32_t count);
extern void initializeTimer1A(uint32_t count);
extern void GPIOConfig(void);
extern void initializeADC(void);
extern void initializePortASpi0(void);
extern bool initializeUART(uint32_t base, uint32_t baudrate);
//*****************************************************************************
//*****************************************************************************


// *******************************************
// Configure SPI
// *******************************************
bool initializeSPI(uint32_t base)
{
	uint32_t delay = 10;
	SPI_PERIPH *myPeriph = (SPI_PERIPH *) base;

	// Turn on the Clock Gating Register
	switch (base) {
	case SSI0:
		{
			// Configure GPIO Port A to support SSI0/SPI0
			initializePortASpi0();
			SYSCTL_RCGCSSI_R |= SYSCTL_RCGCSSI_R0;
			break;
		}
	default:
		return false;
	}

	while (delay != 0) {
		delay--;
	}

	// Disable the SSI interface
	myPeriph->SSICR1 &= ~0x02;

	// Enable Master Mode
	myPeriph->SSICR1 &= ~0x04;

	// Assume that we hvae a 80MHz clock and want a 4MHz SPI clock
	// FSSIClk = FSysClk / (CPSDVSR * (1 + SCR))
	myPeriph->SSICPSR = 20;
	myPeriph->SSICR0 = 0;

	// Clear the phse and polarity bits
	myPeriph->SSICR0 &= ~(SSI_CR0_SPH | SSI_CR0_SPO);

	myPeriph->SSICR0 = SSI_CR0_SPH;

	myPeriph->SSICR0 |= SSI_CR0_SPO;

	// Freescale SPI Mode with 8-Bit data (See line 2226 of lm4f120h5qr.h)
	myPeriph->SSICR0 |= SSI_CR0_DSS_8;

	//Enable SSI
	myPeriph->SSICR1 |= 0x02;

	return true;
}

//*****************************************************************************
// Get the ADC value of a given ADC Channel
// INPUT: POT_LEFT, POT_RIGHT
// Data stored in: POT300Value, POT301Value
//*****************************************************************************
void GetADCval(uint32_t Channel)
{
	uint32_t result;

	ADC0_SSMUX3_R = Channel;	// Set the channel
	ADC0_ACTSS_R |= ADC_ACTSS_ASEN3;	// Enable SS3
	ADC0_PSSI_R = ADC_PSSI_SS3;	// Initiate SS3

	while (0 == (ADC0_RIS_R & ADC_RIS_INR3));	// Wait for END of conversion
	result = ADC0_SSFIFO3_R & 0x0FFF;	// Read the 12-bit ADC result
	ADC0_ISC_R = ADC_ISC_IN3;	// Acknowledge completion

	//return result;
	switch (Channel) {
	case 0:
		{
			POT300Value = result;
			break;
		}
	case 1:
		{
			POT301Value = result;
			break;
		}
	}
}

int main(void)
{
	uint32_t Systick = 0;
	uint32_t Timer0A = 0;

	// Initialize the PLLs so the the main CPU frequency is 80MHz
	PLL_Init();
	initializeSysTick(8000);	// Period: 1ms
	initializeTimer0A(5208);	// Refresh rate: 60Hz
	// PWM: 256
	initializeTimer1A(0);

	//Configure Port C
	initPortC();
	GPIOConfig();
	initializeADC();
	initializeSPI(SSI0);
	initializeUART(UART0, 115200);
	initializeUART(UART2, 115200);
	initializeUART(UART5, 115200);

	while (1) {
		if (mSecondAlert == true) {
			Systick++;
			mSecondAlert = false;
		}
		if (DisplayPWM == true) {
			Timer0A++;
			DisplayPWM = false;
		}
	}

}
